package com.xiqi.microservice.auth.filter;

import com.xiqi.microservice.auth.config.JWTAuthenticationConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

/**
 * @program: authcommons
 * @description: 每个请求都要过滤一次。但是也只过滤一次
 * @author: Shine
 * @create: 2019-08-01 11:55
 */
public class JWTTokenAuthenticationFilter extends OncePerRequestFilter {
    private JWTAuthenticationConfig jwtAuthenticationConfig;

    public JWTTokenAuthenticationFilter() {
    }

    public JWTTokenAuthenticationFilter(JWTAuthenticationConfig jwtAuthenticationConfig) {
        this.jwtAuthenticationConfig = jwtAuthenticationConfig;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //先从请求头里面拿到token
        String token = request.getHeader(jwtAuthenticationConfig.getHeader());

        boolean present = Optional.ofNullable(token).isPresent();
        if (present && token.startsWith(jwtAuthenticationConfig.getPrefix())) {
            //去掉前缀
            token.replace(jwtAuthenticationConfig.getPrefix() + "", "");
            try {

                Claims claims = Jwts.parser().setSigningKey(jwtAuthenticationConfig.getSecret().getBytes()).parseClaimsJws(token).getBody();
                //用户名
                String userName = claims.getSubject();
                List<String> authorities = claims.get("authorities", List.class);
                if (userName != null) {
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userName, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }
            } catch (Exception exception) {
                exception.printStackTrace();
                //清缓存
                SecurityContextHolder.clearContext();
            }

        }
        filterChain.doFilter(request, response);
    }
}
